package utils

import (
	"bufio"
	"crypto/md5"
	"database/sql"
	"encoding/hex"
	"fmt"
	"log"
	"math/rand"
	"net"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	_ "strconv"
	"strings"
	_ "syscall"
	"time"
)

func Chkerr(e error) {
	if e != nil {
		log.Println(e.Error())
	}
}

// 将字符串转换为MD5
func Md5(s string) string {
	md5ctx := md5.New()
	md5ctx.Write([]byte(s))
	cipher := md5ctx.Sum(nil)
	return hex.EncodeToString(cipher)
}

// 查询结果转换为数组MAP
func SqlResolve(rows *sql.Rows) []map[string]interface{} {
	// 获得所有列
	colnums, _ := rows.Columns()
	cols := make([]interface{}, len(colnums))
	vals := make([]interface{}, len(colnums))

	// 关联列与值，组织为键值对
	for i := range vals {
		cols[i] = &vals[i]
	}

	var data []map[string]interface{}
	for rows.Next() {
		// 当前列表存入键值对 值
		rows.Scan(cols...)
		row := make(map[string]interface{})

		for i, col := range vals {
			if col != nil {
				row[colnums[i]] = string(col.([]byte))
			}
		}

		data = append(data, row)
	}
	return data
}

// 平行排列树状结构
func SortTree(data []map[string]interface{}, pid interface{}, level int) ([]map[string]interface{}, error) {
	var newdata []map[string]interface{}
	for _, v := range data {
		if v["pid"] == pid {
			v["html"] = strings.Repeat("---", level)
			newdata = append(newdata, v)

			subdata, _ := SortTree(data, v["id"], level+1)
			for _, v1 := range subdata {
				newdata = append(newdata, v1)
			}
		}

	}
	return newdata, nil
}

// 读取ini文档到MAP
func ReadIniToMap(filename string) map[string]interface{} {
	m := make(map[string]interface{})

	f, err := os.Open(filename)
	if err != nil {
		log.Println(err)
	}
	defer f.Close()

	Bfread := bufio.NewReader(f)
	for {
		line, err := Bfread.ReadBytes('\n')
		s := (strings.TrimSpace(string(line)))
		es := strings.Split(s, "=")
		es0 := strings.TrimSpace(es[0])

		if len(es0) > 0 {
			es1 := strings.TrimSpace(es[1])
			m[es0] = es1
		}

		if err != nil {
			break
		}
	}
	return m
}

// 读取ini文档到数组MAP
func ReadIniToArrMap(filename string) []map[string]interface{} {
	var arr []map[string]interface{}

	f, err := os.Open(filename)
	Chkerr(err)
	defer f.Close()

	Bfread := bufio.NewReader(f)
	for {
		line, err := Bfread.ReadBytes('\n')
		s := (strings.TrimSpace(string(line)))
		es := strings.Split(s, "=")
		es0 := strings.TrimSpace(es[0])

		if len(es0) > 0 {
			es1 := strings.TrimSpace(es[1])
			m := make(map[string]interface{})
			m[es0] = es1
			arr = append(arr, m)
		}

		if err != nil {
			break
		}
	}
	return arr
}

// MAP写入ini文档
func WriteInibyMap(filename string, data map[string]interface{}) error {

	f, err := os.Create(filename)
	for k, v := range data {
		lineString := k + " = " + v.(string) + "\n"
		f.WriteString(lineString)
	}

	if err != nil || len(data) < 1 {
		return err
	}

	return nil
}

// 数组MAP写入ini文档
func WriteInibyArrMap(filename string, data []map[string]interface{}) error {

	f, err := os.Create(filename)
	for _, v := range data {
		for key, val := range v {
			lineString := key + " = " + val.(string) + "\n"
			f.WriteString(lineString)
		}
	}

	if err != nil || len(data) < 1 {
		return err
	}

	return nil
}

//获得本机IP
func GetIp() string {
	conn, err := net.Dial("udp", "www.google.com.hk:80")
	if err != nil {
		log.Println(err.Error())
		return ""
	}
	defer conn.Close()
	return conn.LocalAddr().String()
}

//获得当前路径
func GetCurrentPath() string {
	s, err := exec.LookPath(os.Args[0])
	Chkerr(err)
	i := strings.LastIndex(s, "\\")
	path := string(s[0 : i+1])
	return path
}

//获得系统盘符
func GetLogicalDrives() []string {
	//	kernel32 := syscall.MustLoadDLL("kernel32.dll")
	//	GetLogicalDrives := kernel32.MustFindProc("GetLogicalDrives")
	//	n, _, _ := GetLogicalDrives.Call()
	//	s := FormatInt(int64(n), 2)
	//	var drives_all = []string{"A:", "B:", "C:", "D:", "E:", "F:", "G:", "H:", "I:", "J:", "K:", "L:", "M:", "N:", "O:", "P：", "Q：", "R：", "S：", "T：", "U：", "V：", "W：", "X：", "Y：", "Z："}
	//	temp := drives_all[0:len(s)]
	//	var d []string
	//	for i, v := range s {
	//		if v == 49 {
	//			l := len(s) - i - 1
	//			d = append(d, temp[l])
	//		}
	//	}
	var drives []string
	//	for i, v := range d {
	//		drives = append(drives[i:], append([]string{v}, drives[:i]...)...)
	//	}
	return drives

}



//格式化IP为整型
func Ip2long(ipstr string) (ip uint32) {
	r := `^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})`
	reg, err := regexp.Compile(r)
	if err != nil {
		return
	}
	ips := reg.FindStringSubmatch(ipstr)
	if ips == nil {
		return
	}

	ip1, _ := strconv.Atoi(ips[1])
	ip2, _ := strconv.Atoi(ips[2])
	ip3, _ := strconv.Atoi(ips[3])
	ip4, _ := strconv.Atoi(ips[4])

	if ip1 > 255 || ip2 > 255 || ip3 > 255 || ip4 > 255 {
		return
	}

	ip += uint32(ip1 * 0x1000000)
	ip += uint32(ip2 * 0x10000)
	ip += uint32(ip3 * 0x100)
	ip += uint32(ip4)

	return
}

//格式化IP为字符
func Long2ip(ip uint32) string {
	return fmt.Sprintf("%d.%d.%d.%d", ip>>24, ip<<8>>24, ip<<16>>24, ip<<24>>24)
}

func Substr(str string, start, length int) string {
	rs := []rune(str)
	rl := len(rs)
	end := 0

	if start < 0 {
		start = rl - 1 + start
	}
	end = start + length

	if start > end {
		start, end = end, start
	}

	if start < 0 {
		start = 0
	}
	if start > rl {
		start = rl
	}
	if end < 0 {
		end = 0
	}
	if end > rl {
		end = rl
	}
	return string(rs[start:end])
}

func GetRandInt(n int) int {
	rand.Seed(int64(time.Now().Nanosecond()))
	return rand.Intn(n)
}
